本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。
如果 Client 端的 GraphQL query 指令中的 fields 有誤,向 Server 請求後 React 只會出現請求失敗訊息。
像是執行以下 mutation:
const ADD_LIST = gql`
mutation AddList($listTitle: String!) {
addList(listTitle: $listTitle) {
id
name #這裡應該是 title 才對
}
}
`;
Server 端應回傳的 List 形別只有 title 欄位,沒有 name 欄位,導致請求發送後會收到 status code 400 錯誤訊息:
但並不會顯示是哪個 GraphQL 請求的哪個部分錯誤,這樣要 debug 就傷腦筋了, 所以要另外設定 Apollo Client 的 Error handling 顯示更精確的錯誤訊息。
(圖片來源: Apollo docs)
有關網路通訊以及GraphQL的錯誤訊息會需要利用 Apollo Link 來存取。
Apollo Link 用於設定每當 Apollo Client 執行 GraphQL 請求後的額外操作,可以串起一系列不同的 Link ,例如第一個 Link 將請求資訊寫入 Log ,第二個 Link 在 Header 添加資訊,最後一個 Link 再向 Server 請求這樣。
Apollo 已經有提供一些現成的 Link 物件,其中一個是 onError 這個 Link,使用上會像這樣:
import { onError } from "@apollo/client/link/error";
const link = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
這是官方範例,在出現 GraphQL 錯誤或網路通訊錯誤時顯示訊息。
有了這個 Link 後,還不能直接應用到 Apollo Client 上,要先搭配發送請求給 Server 的 Link。
目前的 ApolloClient instance 長這樣:
const client = new ApolloClient({
uri: "http://localhost:4000/",
cache: new InMemoryCache(),
});
在 ApolloClient 的設定中,可以用 uri 或 link 指定傳送請求的 server,如果兩者並存的話會以 link 優先。
相較 uri , link 可以制定更詳細的請求設定。
使用 link 向 server 發送請求:
import { HttpLink } from "@apollo/client";
const link = new HttpLink({ uri: "http://localhost:4000/" });
const client = new ApolloClient({
cache: new InMemoryCache(),
link: link,
});
如果想串接更多 Link 模塊,就需要用 HttpLink 負責最後向 Server 傳送請求的工作。
接著要將錯誤訊息處理跟請求發送的 Link 串起來,設定給 ApolloClient。
Apollo Client 中的 from 方法,可以接收包含數個 Link 的陣列,包成一個 Link 物件使用。
const link = from([ Link1, Link2 , ... , terminatingLink]);
注意無論中間過程為何,負責向 Server 執行請求的 terminatingLink 必須放在陣列的最後一位。
將 ErrorLogLink 跟 terminatingLink 串接後給 ApolloClient 用:
import {
ApolloClient,
InMemoryCache,
from,
HttpLink,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";
const ErrorLogLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const RequestLink = new HttpLink({
uri: process.env.REACT_APP_APOLLO_SERVER_URL,
});
const link = from([ErrorLogLink, RequestLink]);
const client = new ApolloClient({
link: link,
cache: new InMemoryCache(),
});
這樣當執行了有問題的 GraphQL 請求後,就能在瀏覽器的 console 看見錯誤訊息,知道是哪個 field 出問題了: